As a substitute is not a Pokemon, it can't be captured, so there is no apparent reason why one would be present in a gym. Does anyone have any information about this? Is it maybe to replace the Pokemon of a banned player or such?
From researching around, it seems to be the default model used for when the game fails to load the Pokemon on top of a gym. One (short) GameFAQ mentions:
It's a glitch, seems to be model (it's in the game files just not used) that appears when the actual Pokemon fails to load for whatever reason.
A Reddit post also seems to agree with this:
It seems to be a catch-all for display glitches.
The final bug being reported is that Pokémon models aren't populating correctly over gyms and are instead being replaced with a "substitute doll." No one's really sure why this is happening as of yet, but if it's happening in your game you'll probably notice. The easiest way to fix it is to clear either your app's data cache or the local data in order to force the game to re-fetch the correct models.
It may be just a way for Niantic to represent a glitch in a way that somewhat makes sense (using Substitute to actually substitute for the Pokemon that should be on top of the gym). I will also note that many believe it may have been part of an April Fools event by Niantic but not much seems to be available on that.