This version of the subquery will only need run once for the entire query, rather than for each row of the outer query.
SELECT c.id, c.franquicia_id, f.name
   , CONCAT(c.name,' ',c.surname) AS contacto
   , c.created, DATE_FORMAT(c.created,'%d-%m-%Y') AS fecha 
FROM contacts AS c 
INNER JOIN franquicias AS f
   ON c.franquicia_id = f.id
    AND f.contract_id=2 
WHERE (c.franquicia_id, c.created) IN (
          SELECT franquicia_id, max(created) 
          FROM contacts
          GROUP BY franquicia_id
) 
ORDER BY created DESC 
LIMIT 10
Alternatively, the subquery can instead be used in an additional JOIN for filtering.
f.contract_id=2 can be put in either the ON or the WHERE; but (and the optimizer may eliminate any difference), keeping it in the ON could potentially reduce rows checked in the where, and makes it easier to later convert the query to a LEFT JOIN if it is ever needed to find "most recent contacts with no f's of contract_id 2".
Note: Indexing (franquicia_id, created) should improve the subquery, and the IN used against it; it should also improve the existing JOIN condition on franquicia_id.