On it's face, it's simple enough, right? Use roles/permissions to hide the categories you don't want your end users seeing during incident submission. But, if you do that, then they also don't have the ability to use the service catalog items which were designed around those categories.
Example: We have a category for "Access Request" - this category (and all of the relevant custom fields/forms associated with it) were built specifically for a service catalog item, with a corresponding approval workflow. If someone navigates to the service catalog, and selects the access request, everything works as intended. But, if they are submitting a regular incident, they can still see and select that "access request" category - with none of the custom fields/forms and workflow associated with it. Now I have an end user (dozens or hundreds, really) which say "But I submitted a request" when they did not. They submitted a ticket that has a "request" category, which does not accomplish the same task. 
Because both service catalog items and incidents are all considered incidents on the back end I can't sort out a way to do this, aside from the current process of manually informing end users that "no, you didn't actually submit a request. yes, you actually have to do it again the right way". I've seen a handful of feature requests going back years about this same issue, but I'm not aware of anything that's addressed it. Even if there was some way to setup an automation rule like "if category = X, check for presence of a workflow, if null, then Auto-comment/close"
How is everyone else handling this?