Ooh, ooh, I just learned the answer to this one, so I'm happy to share the love. That you noticed that indicates that you have a good eye.
"When preceded by avere, participle does not change in gender and number except when the direct object pronoun (what substitutes la torta or le rane) moves behind the auxiliary."
In this case, the speaker is one of a group of women, and since there is a "ci" particle appearing before the "ha", the participle matches the gender and number of the direct object (in this case, although it doesn't actually appear, that would be ragazze or donne).
See this answer for a longer and probably more accurate explanation: http://duolingo.com/#/comment/271063
So actually the pronoun "ci" is substituting for "noi ragazze," not actually a general "we" like we think in English, where it only can be a neutral word, or where there is no such thing as altering verbs to accommodate gender/ number.
I think that if it were referring to a group of people of mixed gender or males, it would have to be Lui ci ha portati allo zoo.
Just to add on to the discussion a bit, when the direct object pronouns lo, la, l', li, and le directly precede the transitive verb (a verb conjugated with avere) in the present perfect, the agreement of the past participle (in gender and number) with the pronoun is mandatory.
However, if the verb is directly preceded by mi, ti, ci, or vi, for example, as in this case, the agreement is completely optional. Thus, this sentence could also have been written "Lui ci ha portatO allo zoo." This gives you some options. :D Hope this helps!
"Verbs of movement" is an easy-to-understand way of explaining which verbs take "avere" and which take "essere", however is not a 100% accurate method.
Transitive verbs (verbs capable of taking a direct object) take "avere".
Intransitive verbs (verbs incapable of taking a direct object, so often verbs of motion like "go") take "essere".
Since "portare" can take a direct object, it takes "avere".