How to partially merge a row in Postgres?
You can simple use lag window function to get the value of the previous row and compare with the current one, then you use CASE to conditionally format as you please. Mapping the "merged" values as NULL (so it can work for any type), it would be:

SELECT
  CASE
  WHEN customers.id = lag(customers.id) OVER w_ordered THEN
    NULL
  ELSE
    customers.first_name
  END AS "Name",
  CASE
  WHEN customers.id = lag(customers.id) OVER w_ordered THEN
    NULL
  ELSE
    customers.last_name
  END AS "Last Name",
  items.name AS "Item",
  items.price AS "Price",
  COUNT(items.id) AS "Amount",
  SUM(items.price) AS "Total"
FROM
  items
INNER JOIN
  purchases ON items.id = purchases.item_id
INNER JOIN
    customers ON purchases.customer_id = customers.id
GROUP BY
  customers.id, items.id
WINDOW
  w_ordered AS (ORDER BY customers.last_name)
ORDER BY customers.last_name


Notice that I used the same ORDER BY clause in the window function as the full query, this is really important because you do want to verify the "merging" following the same rule.

Now, this is not a presentation mode, as in SQL you only have a table as a result, if you wish to do a real row merging in your presentation layer, you can use another column to just inform if it should merge the rows or not (although it shouldn't be hard to do the full logic there).