If it would be an exact representation of OO then the generalization principle should do the trick. Especially if you have a lot of attributes on animal level which recurs in all child objects.
If it would only be 1 or 2 common attributes and you want to work with large sets of data then you could choose for a little redudancy for the sake of performance and not generalize these "make sound" attributes.
I'm sorry, I saw your question as a property of the generalized object instead of functionality. So if you would want to save a sound file for each generalization you could make this runtime configurable. You create a general settings object, then you create an association from the sound file to the settings object for each generalization. You then have the choice to either create one big sub microflow, create a GetOrCreate microflow for the settings object and based on the inherentance split retrieve the correct sound file over association. Then you can have just one main flow to execute the behaviour and you can re-use this from every generalization or you can create a microflow for each generalization and retrieve the correct sound file over association.