what might be worth a test is to only process a maximum number of messages for each render.
this would help, if there are 'peaks' in the flow as it would even them out a bit.
it won't help much if the flow is continuously very high, and it would introduce latency.
(in that case, Id think thinning really is the only option)
what I'd also check is that its not the patches processing of the midi messages thats not too computationally expensive e.g. if you remove the processing, do you still get underruns.
if not, then you'd likely be able to do the thinning in the patch.
one thing Ive seen with some expressive controllers is continuous expressions can 'bounce' around quite a bit.
i.e. when you think your finger is holding a steady pressure, it might be bouncing between cc74 = 65,66,65 at the full data rate (which could be 250-500 msg/sec). this really needs to be smoothed, I usually use a cheap low pass filter (or similar...)
imo, it also often ends up sounding better - e.g. without this my Soundplane can sound quite 'jittery'.
note: this depends upon controller and its software, often the software/firmware will have this filtering as an options, as its a really effective way to reduce data.