After working with Clodoaldo Neto's answer a while, I finally got it.
WITH matches AS (
select t1.id id1, t2.id id2
from temp t1
inner join temp t2 on t1.id < t2.id
where f(t1.data, t2.data)
)
SELECT id1 || ARRAY_AGG(id2)
FROM matches
WHERE id1 NOT IN (SELECT DISTINCT id2 FROM matches)
GROUP BY id1
SQL Fiddle: http://sqlfiddle.com/#!12/57b97/14
The CTE comes straight from Clodoaldo Neto's inner query. This is really nice because it also lets me split them and have the lowest ID by itself if I want:
WITH matches AS (select t1.id id1, t2.id id2
from temp t1
inner join temp t2 on t1.id < t2.id
where f(t1.data, t2.data)
)
SELECT id1, ARRAY_AGG(id2) AS duplicates
FROM matches
WHERE id1 NOT IN (SELECT DISTINCT id2 FROM matches)
GROUP BY id1